﻿using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Options;
using SXICE.Core.Configs;
using SXICE.Core.Infrastructure;
using System;

namespace SXICE.AdminAPI.Infrastructure
{
    /// <summary>
    /// 默认本地缓存
    /// </summary>
    public class DefaultLocalCache : ILocalCache
    {
        public DefaultLocalCache(CacheConfigs cacheConfigs)
        {
            memoryCache = new MemoryCache(new MemoryCacheOptions { SizeLimit = cacheConfigs.SizeLimit });
        }

        /// <summary>
        /// 缓存
        /// </summary>
        private readonly MemoryCache memoryCache = null;

        public bool Exists(string key)
        {
            return memoryCache.TryGetValue(key, out var result);
        }

        public void Remove(string key)
        {
            memoryCache.Remove(key);
        }

        public void Set<T>(string key, T value, TimeSpan? slideExpireTime = null, DateTime? absoluteExpireTime = null)
        {
            var memoryCacheOptions = new MemoryCacheEntryOptions();
            if (slideExpireTime.HasValue)
                memoryCacheOptions.SlidingExpiration = slideExpireTime.Value;
            if (absoluteExpireTime.HasValue)
                memoryCacheOptions.AbsoluteExpiration = absoluteExpireTime.Value;
            memoryCache.Set(key, value, memoryCacheOptions);
        }

        public bool TryGet<T>(string key, out T obj)
        {
            if (null == key)
            {
                obj = default(T);
                return false;
            }
            return memoryCache.TryGetValue(key, out obj);
        }

        public T GetOrAdd<T>(string key, Func<T> func, TimeSpan? slidingExpiration = null, DateTime? absoluteExpiration = null)
        {
            return memoryCache.GetOrCreate<T>(key, entry =>
            {
                if (slidingExpiration.HasValue)
                    entry.SlidingExpiration = slidingExpiration.Value;
                if (absoluteExpiration.HasValue)
                    entry.AbsoluteExpiration = absoluteExpiration.Value;
                return func();
            });
        }

        public void AddOrUpdate<T>(string key, T obj)
        {
            memoryCache.Set(key, obj);
        }

        ~DefaultLocalCache()
        {
            memoryCache.Dispose();
        }
    }
}
